using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using DifferenceEngine;
using System.Collections;

namespace GeneratorLibrary.Client.Base {
    public partial class DiffResolver : Form {
        private class ChangeItem {
            public bool changeToSource;
            public string oldValue;
            public string newValue;
            public Color oldSourceColor;
            public Color oldDestinationColor;
            public int index;
        }
        List<List<ChangeItem>> ChangeList = new List<List<ChangeItem>>();


        public DiffResolver(DiffList_Text source, DiffList_Text destination, ArrayList DiffLines) {
            InitializeComponent();

            ListViewItem lviS;
            ListViewItem lviD;
            int cnt = 1;
            int i;

            foreach (DiffResultSpan drs in DiffLines) {
                switch (drs.Status) {
                    case DiffResultSpanStatus.DeleteSource:
                        for (i = 0; i < drs.Length; i++) {
                            lviS = new ListViewItem(cnt.ToString("00000"));
                            lviD = new ListViewItem(cnt.ToString("00000"));
                            lviS.BackColor = Color.Red;
                            lviS.SubItems.Add(((TextLine)source.GetByIndex(drs.SourceIndex + i)).Line);
                            lviD.BackColor = Color.LightGray;
                            lviD.SubItems.Add("");

                            lvSource.Items.Add(lviS);
                            lvDestination.Items.Add(lviD);
                            cnt++;
                        }

                        break;
                    case DiffResultSpanStatus.NoChange:
                        for (i = 0; i < drs.Length; i++) {
                            lviS = new ListViewItem(cnt.ToString("00000"));
                            lviD = new ListViewItem(cnt.ToString("00000"));
                            lviS.BackColor = Color.White;
                            lviS.SubItems.Add(((TextLine)source.GetByIndex(drs.SourceIndex + i)).Line);
                            lviD.BackColor = Color.White;
                            lviD.SubItems.Add(((TextLine)destination.GetByIndex(drs.DestIndex + i)).Line);

                            lvSource.Items.Add(lviS);
                            lvDestination.Items.Add(lviD);
                            cnt++;
                        }

                        break;
                    case DiffResultSpanStatus.AddDestination:
                        for (i = 0; i < drs.Length; i++) {
                            lviS = new ListViewItem(cnt.ToString("00000"));
                            lviD = new ListViewItem(cnt.ToString("00000"));
                            lviS.BackColor = Color.LightGray;
                            lviS.SubItems.Add("");
                            lviD.BackColor = Color.LightGreen;
                            lviD.SubItems.Add(((TextLine)destination.GetByIndex(drs.DestIndex + i)).Line);

                            lvSource.Items.Add(lviS);
                            lvDestination.Items.Add(lviD);
                            cnt++;
                        }

                        break;
                    case DiffResultSpanStatus.Replace:
                        for (i = 0; i < drs.Length; i++) {
                            lviS = new ListViewItem(cnt.ToString("00000"));
                            lviD = new ListViewItem(cnt.ToString("00000"));
                            lviS.BackColor = Color.Red;
                            lviS.SubItems.Add(((TextLine)source.GetByIndex(drs.SourceIndex + i)).Line);
                            lviD.BackColor = Color.LightGreen;
                            lviD.SubItems.Add(((TextLine)destination.GetByIndex(drs.DestIndex + i)).Line);

                            lvSource.Items.Add(lviS);
                            lvDestination.Items.Add(lviD);
                            cnt++;
                        }

                        break;
                }

            }
        }
        private void lvSource_Resize(object sender, System.EventArgs e) {
            if (lvSource.Width > 100) {
                lvSource.Columns[1].Width = -2;
            }
        }

        private void lvDestination_Resize(object sender, System.EventArgs e) {
            if (lvDestination.Width > 100) {
                lvDestination.Columns[1].Width = -2;
            }
        }

        private void DiffResolver_Resize(object sender, System.EventArgs e) {
            int w = this.ClientRectangle.Width / 2;
            lvSource.Location = new Point(0, 41);
            lvSource.Width = w;
            lvSource.Height = this.ClientRectangle.Height - 41;

            lvDestination.Location = new Point(w + 1, 41);
            lvDestination.Width = this.ClientRectangle.Width - (w + 1);
            lvDestination.Height = this.ClientRectangle.Height - 41;
        }

        private void DiffResolver_Load(object sender, System.EventArgs e) {
            DiffResolver_Resize(sender, e);
        }

        private void lvSource_SelectedIndexChanged(object sender, System.EventArgs e) {
            if (lvSource.SelectedItems.Count > 0) {
                ListViewItem lvi = lvDestination.Items[lvSource.SelectedItems[0].Index];
                lvi.Selected = true;
                lvi.EnsureVisible();
            }
        }

        private void lvDestination_SelectedIndexChanged(object sender, System.EventArgs e) {
            if (lvDestination.SelectedItems.Count > 0) {
                ListViewItem lvi = lvSource.Items[lvDestination.SelectedItems[0].Index];
                lvi.Selected = true;
                lvi.EnsureVisible();
            }
        }

        private void ApplyChange(List<ChangeItem> changes){
            foreach (ChangeItem change in changes) {
                if (change.changeToSource) {
                    lvDestination.Items[change.index].BackColor = Color.White;

                    lvSource.Items.RemoveAt(change.index);
                    lvSource.Items.Insert(change.index, (ListViewItem)lvDestination.Items[change.index].Clone());
                } else {
                    lvSource.Items[change.index].BackColor = Color.White;

                    lvDestination.Items.RemoveAt(change.index);
                    lvDestination.Items.Insert(change.index, lvSource.Items[change.index]);
                }
            }
        }
        private void UndoChange(List<ChangeItem> changes) {
            foreach (ChangeItem change in changes) {
                lvDestination.Items[change.index].BackColor = change.oldDestinationColor;
                lvSource.Items[change.index].BackColor = change.oldSourceColor;

                if (change.changeToSource) {
                    lvSource.Items[change.index].SubItems[1].Text = change.oldValue;
                } else {
                    lvDestination.Items[change.index].SubItems[1].Text = change.oldValue;
                }
            }
        }

        private void btnSaveSourceChange_Click(object sender, EventArgs e) {
            List<ChangeItem> changeSet = new List<ChangeItem>();
            foreach (ListViewItem l in lvSource.SelectedItems) {
                if (l.BackColor != Color.White) {
                    ChangeItem c = new ChangeItem();

                    c.changeToSource = false;
                    c.index = l.Index;
                    c.newValue = l.SubItems[1].Text;
                    c.oldValue = lvDestination.Items[l.Index].SubItems[1].Text;
                    c.oldDestinationColor = lvDestination.Items[l.Index].BackColor;
                    c.oldSourceColor = l.BackColor;
                    changeSet.Add(c);
                }
            }
            if (changeSet.Count > 0) {
                ApplyChange(changeSet);
                this.ChangeList.Add(changeSet);
            }
        }

        private void btnSaveDestinationChange_Click(object sender, EventArgs e) {
            List<ChangeItem> changeSet = new List<ChangeItem>();
            foreach (ListViewItem l in lvDestination.SelectedItems) {
                if (l.BackColor != Color.White) {
                    ChangeItem c = new ChangeItem();

                    c.changeToSource = true;
                    c.index = l.Index;
                    c.newValue = l.SubItems[1].Text;
                    c.oldValue = lvSource.Items[l.Index].SubItems[1].Text;
                    c.oldDestinationColor = l.BackColor;
                    c.oldSourceColor = lvSource.Items[l.Index].BackColor;
                    changeSet.Add(c);
                }
            }
            if (changeSet.Count > 0) {
                ApplyChange(changeSet);
                this.ChangeList.Add(changeSet);
            }
        }

        private void btnSave_Click(object sender, EventArgs e) {
            this.DialogResult = DialogResult.OK;
        }
        public string GetSourceLines(){
            StringBuilder result = new StringBuilder();
            foreach (ListViewItem l in lvSource.Items) {
                result.AppendLine(l.SubItems[1].Text);
            }
            return result.ToString();
        }
        public string GetDestinationLines() {
            StringBuilder result = new StringBuilder();
            foreach (ListViewItem l in lvDestination.Items) {
                result.AppendLine(l.SubItems[1].Text);
            }
            return result.ToString();
        }

        private void btnUndo_Click(object sender, EventArgs e) {
            if (ChangeList.Count == 0)
                return;

            List<ChangeItem> changeSet = ChangeList[ChangeList.Count - 1];
            UndoChange(changeSet);
            ChangeList.RemoveAt(ChangeList.Count - 1);
        }
    }
}